查看原文
其他

ollvm算法还原案例分享

咸鱼炒白菜 看雪学院 2021-03-07

本文为看雪论坛优秀文章

看雪论坛作者ID:咸鱼炒白菜



本文为看雪安卓高研3w班(5月班)优秀学员作品。


下面先让我们来看看讲师对学员学习成果的点评,以及学员的学习心得吧!


讲师点评

分析被ollvm混淆的算法思路就是找到参数被加密的过程以及结果的生成过程,frida的Thread.backtrace得到调用栈可以快速分析出参数的加密过程,再结合ida trace可以分析出参数被加密的具体算法。


trace日志太大的时候,参数加密过程比较多,可以从trace日志中找返回结果的生成过程,来定位到具体算法的地址。




学员感想


样本来自看雪3W班5月题。


本题主要是还原so的算法函数,关键算法函数很好定位,主要还原方法是frida+ida调试+ida trace。


ps. 题目附件请点击“阅读原文”下载。

现在,看雪《安卓高级研修班(网课)》9月班开始招生啦!点击查看详情报名吧~


1



解题步骤




1. 找到对应产生结果的函数public native byte[] e(byte[] arg1)。

public class MainActivity extends AppCompatActivity { static { System.loadLibrary("native-lib"); } public native byte[] d(byte[] arg1) { } public native byte[] e(byte[] arg1) { } @Override // androidx.appcompat.app.AppCompatActivity protected void onCreate(Bundle arg3) { super.onCreate(arg3); this.setContentView(0x7F09001C); // layout:activity_main TextView v3 = (TextView)this.findViewById(0x7F070061); // id:sample_text StringBuilder v0 = new StringBuilder(); v0.append("pediy_imyang_"); v0.append(RandomStringUtils.randomAlphabetic(10)); v3.setText(ByteString.of(this.e(v0.toString().getBytes())).hex()); }}

2. 固定入参,打印参数。

function hook_java(){ Java.perform(function () { //org.apache.commons.lang3.RandomStringUtils.randomAlphabetic(int): java.lang.String var RandomStringUtils = Java.use("org.apache.commons.lang3.RandomStringUtils"); RandomStringUtils.randomAlphabetic.overload('int').implementation = function(arg){ var result = this.randomAlphabetic(arg); // console.log("org.apache.commons.lang3.RandomStringUtils.randomAlphabetic:", result); result = "lXcaTALmow"; return result; } //com.kanxue.ollvm5.MainActivity.encryt(byte[]): byte[] var ByteString = Java.use("com.android.okhttp.okio.ByteString"); var MainActivity = Java.use("com.kanxue.ollvm5.MainActivity"); MainActivity.e.implementation = function(arg){ var result = this.e(arg); console.log("com.kanxue.ollvm5.MainActivity arg:", ByteString.of(arg).hex()); console.log("com.kanxue.ollvm5.MainActivity result:", ByteString.of(result).hex()); return result; } });}

得到结果:

com.kanxue.ollvm5.MainActivity arg: 70656469795f696d79616e675f6c58636154414c6d6f77com.kanxue.ollvm5.MainActivity result: 797903090001a4b8b6c89eb47f4f29b44d47c7382f851ad57618f9b820c5d55298cb5f941c8c

3. IDA打开对应so,找到jbyteArray __fastcall Java_com_kanxue_ollvm5_MainActivity_e(JNIEnv *env_, __int64 a2, jbyteArray ary)函数,hook发现sub_184EC调用三次,其中第三次的arg1为结果函数。

sub_184EC(&arg0, arg1, arg2);`

查找sub_184EC引用,找到函数sub_13CE4:

__int64 __fastcall sub_13CE4(__int64 result, unsigned int a2, __int64 a3, unsigned int a4, __int64 output)

4. hook sub_184EC, 根据结果可知参数类型,第2个参数是input,第5个参数是ouput,即sub_184EC为关键算法函数。

//13CE4var addr_13CE4 = base.add(0x13CE4);var arg13CE4_0;var arg13CE4_1;var arg13CE4_4;Interceptor.attach(addr_13CE4, { onEnter: function (args) { //var r2 = this.context.r2; arg13CE4_0 = args[0]; arg13CE4_1 = args[1]; arg13CE4_4 = args[4]; console.log("addr_13CE4 onEnter args0", hexdump(args[0])); //input console.log("addr_13CE4 onEnter args1", args[1]); //inputlen console.log("addr_13CE4 onEnter args4", hexdump(args[4])); }, onLeave: function (retval) { console.log("addr_13CE4 onLeave args0", hexdump(arg13CE4_0)); console.log("addr_13CE4 onLeave args1", arg13CE4_1); console.log("addr_13CE4 onLeave args4", hexdump(arg13CE4_4)); // console.log("addr_13CE4 retval", hexdump(arg1)); }});

frida写一个主动调用,trace一下:

function call_e() { //主动调用函数 //com.kanxue.ollvm5.MainActivity.e(byte[]): byte[] Java.perform(function () { var MainActivity = Java.use("com.kanxue.ollvm5.MainActivity"); Java.choose("com.kanxue.ollvm5.MainActivity", { onMatch: function (instance) { //pediy_imyang_lXcaTALmow var buffer = Java.array('byte', [0x70, 0x65, 0x64, 0x69, 0x79, 0x5f, 0x69, 0x6d, 0x79, 0x61, 0x6e, 0x67, 0x5f, 0x6c, 0x58, 0x63, 0x61, 0x54, 0x41, 0x4c, 0x6d, 0x6f, 0x77]) var result = instance.e(buffer); var ByteString = Java.use("com.android.okhttp.okio.ByteString"); console.log(ByteString.of(result).hex()) }, onComplete: function () { } }); });}

从trace的结果来看只看到input没看到output。
再返回仔细看,尝试hook sub_13808试试:

[AOSP on msm8996::com.kanxue.ollvm5]-> android_dlopen_ext: /data/app/com.kanxue.ollvm5-BHVsEeMGCcVFJqvmRywKWw==/lib/arm64/libnative-lib.soaddr_13CE4 onEnter args0 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF71103c3940 70 65 64 69 79 5f 69 6d 79 61 6e 67 5f 6c 58 63 pediy_imyang_lXc71103c3950 61 54 41 4c 6d 6f 77 00 63 74 69 76 69 74 79 00 aTALmow.ctivity.71103c3960 60 74 22 10 71 00 00 00 a0 3a 3c 10 71 00 00 00 `t".q....:<.q...71103c3970 d8 2e 07 05 71 00 00 00 7a 69 70 3a 00 00 00 00 ....q...zip:.... 71103c3980 40 39 3c 10 71 00 00 00 78 2f f9 1f b9 bb 45 f9 @9<.q...x/....E.71103c3990 88 61 d2 6f 00 00 00 00 01 69 70 3a 0d 00 00 00 .a.o.....ip:....71103c39a0 e0 38 3c 10 71 00 00 00 c2 0c ec de f4 c9 52 69 .8<.q.........Ri71103c39b0 b0 72 20 f7 70 00 00 00 01 69 70 3a 0e 00 00 00 .r .p....ip:....71103c39c0 e0 39 3c 10 71 00 00 00 9c 37 53 f8 65 b6 7c 4b .9<.q....7S.e.|K71103c39d0 e0 72 20 f7 70 00 00 00 01 69 70 3a 0f 00 00 00 .r .p....ip:....71103c39e0 80 39 3c 10 71 00 00 00 3c 06 6b 29 07 5f ca 6f .9<.q...<.k)._.o71103c39f0 10 73 20 f7 70 00 00 00 01 69 70 3a 10 00 00 00 .s .p....ip:....71103c3a00 c0 39 3c 10 71 00 00 00 db 0c 87 26 01 e5 1f 47 .9<.q......&...G71103c3a10 40 73 20 f7 70 00 00 00 01 69 70 3a 11 00 00 00 @s .p....ip:....71103c3a20 60 39 3c 10 71 00 00 00 93 20 5d c7 0a 4f 29 a9 `9<.q.... ]..O).71103c3a30 78 c7 c5 6f 00 00 00 00 e0 c9 38 10 71 00 00 00 x..o......8.q...addr_13CE4 onEnter args1 0x17addr_13808 onEnter args0 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF79ff4fd210 77 77 77 2e 70 65 64 69 79 2e 63 6f 6d 26 6b 61 www.pediy.com&ka79ff4fd220 6e 78 75 65 00 00 00 00 79 79 00 00 00 00 00 00 nxue....yy......79ff4fd230 62 61 73 69 63 5f 73 74 72 69 6e 67 00 00 00 00 basic_string....79ff4fd240 61 6c 6c 6f 63 61 74 6f 72 3c 54 3e 3a 3a 61 6c allocator<T>::aladdr_13808 onEnter args1 0x14addr_13808 onLeave args2 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF7fdcb5fe70 31 f5 f5 f5 f9 43 4d 51 a8 fb 31 b6 ef 7f f7 3c 1....CMQ..1....<7fdcb5fe80 40 ba 21 9d 7a 00 00 00 17 00 00 00 00 00 00 00 @.!.z...........7fdcb5fe90 46 9d 4c 18 7a 00 00 00 00 00 00 00 09 00 00 00 F.L.z...........7fdcb5fea0 60 75 49 18 7a 00 00 00 40 9d 4c 18 17 00 00 00 `uI.z...@.L.....7fdcb5feb0 10 d2 4f ff 79 00 00 00 14 00 00 00 00 00 00 00 ..O.y...........addr_172D0 onEnter args0 0xb6cff93caddr_172D0 onLeave retval 0xcff93cb6addr_172D0 onEnter args0 0xb6ef9f85addr_172D0 onLeave retval 0x9f85b6efaddr_172D0 onEnter args0 0xcf506afbaddr_172D0 onLeave retval 0xfbcf506aaddr_172D0 onEnter args0 0x3ca8f563addr_172D0 onLeave retval 0xa8f5633caddr_172D0 onEnter args0 0x63636363addr_172D0 onLeave retval 0x63636363addr_172D0 onEnter args0 0x63636363addr_172D0 onLeave retval 0x63636363addr_13CE4 onLeave args4 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF71102c8e70 79 79 03 09 00 01 a4 b8 b6 c8 9e b4 7f 4f 29 b4 yy...........O).71102c8e80 4d 47 c7 38 2f 85 1a d5 76 18 f9 b8 20 c5 d5 52 MG.8/...v... ..R71102c8e90 98 cb 5f 94 1c 8c 38 3c 55 0b 00 00 00 00 00 00 .._...8<U.......71102c8ea0 4a 61 76 61 5f 63 6f 6d 5f 6b 61 6e 78 75 65 5f Java_com_kanxue_71102c8eb0 6f 6c 6c 76 6d 35 5f 4d 61 69 6e 41 63 74 69 76 ollvm5_MainActiv71102c8ec0 69 74 79 5f 65 00 00 00 56 0b 00 00 00 00 00 00 ity_e...V.......71102c8ed0 80 a2 2c 10 71 00 00 00 71 54 b6 27 19 57 c7 d8 ..,.q...qT.'.W..71102c8ee0 00 00 00 00 00 00 00 00 db d0 cf 94 71 00 00 00 ............q...71102c8ef0 0e 00 00 00 00 00 00 00 57 0b 00 00 00 00 00 00 ........W.......71102c8f00 10 a6 2c 10 71 00 00 00 3b 29 67 2f d8 63 3f 36 ..,.q...;)g/.c?671102c8f10 00 00 00 00 00 00 00 00 01 d1 cf 94 71 00 00 00 ............q...71102c8f20 13 00 00 00 00 00 00 00 b8 0b 00 00 00 00 00 00 ................71102c8f30 00 8f 2c 10 71 00 00 00 12 6d 28 cd 75 ae c6 d4 ..,.q....m(.u...71102c8f40 00 00 00 00 00 00 00 00 25 d1 cf 94 71 00 00 00 ........%...q...71102c8f50 18 00 00 00 00 00 00 00 c2 0b 00 00 00 00 00 00 ................71102c8f60 90 95 2c 10 71 00 00 00 52 af da eb a8 27 dd ed ..,.q...R....'..com.kanxue.ollvm5.MainActivity arg: 70656469795f696d79616e675f6c58636154414c6d6f77com.kanxue.ollvm5.MainActivity result: 797903090001a4b8b6c89eb47f4f29b44d47c7382f851ad57618f9b820c5d55298cb5f941c8c

一步一步调试,发现第一轮最先生成的是:

79 79 03 09 00 0151 4D 43 F9B6 CF F9 3CB6 EF 9F 85CF 50 6A FBEF 20 83 293C A8 F5 6363 63 63 6363 63 63 63

然后才生成结果:

79 79 03 09 00 01a4 b8 b6 c89e b4 7f 4f29 b4 4d 47c7 38 2f 851a d5 76 18f9 b8 20 c5d5 52 98 cb5f 94 1c 8c

根据trace + 第一轮生成结果比对,还原出最终算法代码如下:

static char keytb_42210[] = { 0x77, 0x77, 0x77, 0x2e, 0x70, 0x65, 0x64, 0x69, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x26, 0x6b, 0x61, 0x6e, 0x78, 0x75, 0x65, 0x00 }; static char keytbde[] = { 0x31, 0xf5, 0xf5, 0xf5, 0xf9, 0x43, 0x4d, 0x51, 0xa8, 0xfb, 0x31, 0xb6, 0xef, 0x7f, 0xf7, 0x3c, 0x40, 0xba, 0x21, 0x9d, 0x7a, 0x00 }; static char byte_42228[] = {0x79, 0x79, 0x00, 0x00}; static char byte_42108[] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };void sub_13808(char* tb, int tblen, char* output){ //本函数从keytb_42210 解析出 keytbde} int REV(int val){ return (((val << 24) & 0xFF000000) | ((val << 8) & 0x00FF0000) | ((val >> 8) & 0x0000FF00) | ((val >> 24) & 0x000000FF));} int keygen_13CE4(const char* input, unsigned int inputlen, char* tb, unsigned int tblen, char* output){ char* o13808 = new char[0x20]; sub_13808(tb, tblen, o13808); output[0] = byte_42228[0]; //LOGD("%0x %0x",0, output[0]); output[1] = byte_42228[1]; output[2] = 0x03; output[3] = (-inputlen ^ 0xFFFFFFF0) & -inputlen;; output[4] = 0; output[5] = 1; //LOGD("%0x %0x",3, output[3]); //LOGD("%0x %0x",4, output[4]); for(int i = 6; i <= 0x25; i++){ int index = input[i - 6]; if(i - 6 >= inputlen){ output[i] = byte_42108[0]; //LOGD("%0x %0x",i, output[i]); continue; } output[i] = byte_42108[index]; //LOGD("%0x %0x",i, output[i]); } for(int i = 0; i < tblen; i++){ int index = tb[i]; tb[i] = byte_42108[index]; //LOGD("tb %0x %0x",i, tb[i]); } for(int i = 0; i <= (0x25 - 0x6)/4; i++){ unsigned int tmp1 = 0; memcpy(&tmp1, keytbde+4*(i%4), sizeof(int)); //LOGD("tmp1 %0x", tmp1); unsigned int tmp2 = 0; memcpy(&tmp2, output + i*4 + 6, sizeof(int)); //LOGD("tmp2 %0x", tmp2); tmp2 = (tmp2 >> 8*(i%4)) | (tmp2 << 32 - 8*(i%4)); //LOGD("tmp2 %0x", tmp2); tmp2 = REV(tmp2); int outputtmp = REV(tmp1 & ~tmp2 | tmp2 & ~tmp1); LOGD("outputtmp %0x", outputtmp); memcpy(output+(6+i*4), &outputtmp, sizeof(int)); } for(int i=0; i<=0x25; i++){ LOGD("output %0x %0x", i, output[i]); } return 0;} void main(){ int tblen = strlen(keytb); const char* input = "pediy_imyang_lXcaTALmow"; char* output = new char[0x200]; keygen_13CE4(input, strlen(input), keytb_42210, tblen, output);}



- End -


看雪ID:咸鱼炒白菜

https://bbs.pediy.com/user-752228.htm

  *本文由看雪论坛 咸鱼炒白菜 原创,转载请注明来自看雪社区。




推荐文章++++

* 举杯邀Frida,对影成三题

* CVE-2020-0624 win32k漏洞分析笔记

* Galgame汉化中的逆向(三):自定义字库分析

* Galgame汉化中的逆向(二):系统字库与文字编码

* 初试IDA&FRIDA联合调试简单ollvm保护的加密函数源码

好书推荐











公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com



ps. 觉得对你有帮助的话,别忘点分享,点赞和在看,支持看雪哦~


“阅读原文”一起来充电吧!

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存